package com.dd.ent.car.common.util;

import android.annotation.SuppressLint;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;

/**
 * 判断网络的工具类
 * <p>
 * 所需的权限:
 * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
 * </p>
 * Created by lixianpeng on 2016/3/29.
 * Copyright (c) 2016 Xunlei. All rights reserved.
 *
 * @author lixianpeng
 * @since 1.0
 */
@SuppressWarnings("unused")
public abstract class NetworkHelper {

    /**
     * {@hide}
     */
    private NetworkHelper() {
    }

    /**
     * 当前网络是否可用
     *
     * @param context Context
     * @return 网络可用返回 {@code true}
     */
    public static boolean isNetworkAvailable(Context context) {
        Context ctx = context.getApplicationContext();
        ConnectivityManager cm = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm != null) {
            NetworkInfo networkInfo = cm.getActiveNetworkInfo();
            if (networkInfo != null && networkInfo.isConnected() && networkInfo.isAvailable()) {
                return true;
            }
            return false;
        } else {
            return false;
        }
    }


    /**
     * 获取当前网络类型
     *
     * @param context Context
     * @return 网络类型: {@link ConnectivityManager} 中定义的网络类型
     */
    public static int getActiveNetworkType(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm != null) {
            NetworkInfo ni = cm.getActiveNetworkInfo();
            if (ni != null) {
                return ni.getType();
            }
        }
        return -1;
    }

    /**
     * 返回当前网络类型名称,
     * 以网络编码格式返回，如 wifi/3gnet/3gwap/uninet/uniwap/cmnet/cmwap/ctnet/ctwap
     *
     * @param context Context
     * @return 网络类型名称
     */
    @SuppressLint("DefaultLocale")
    public static String getActiveNetworkTypeName(Context context) {
        String typeName = "null";
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm == null) {
            return typeName;
        }
        NetworkInfo info = cm.getActiveNetworkInfo();
        if (info == null) {
            return typeName;
        }
        if (info.getTypeName() != null) {
            typeName = info.getTypeName().toLowerCase(); // wifi / mobile
            if (!typeName.equals("wifi")) {
                if (info.getExtraInfo() != null) {
                    // 3gnet/3gwap/uninet/uniwap/cmnet/cmwap/ctnet/ctwap
                    typeName = info.getExtraInfo().toLowerCase();
                }
                if (typeName.equals("#777") && info.getSubtypeName() != null) {
                    typeName = info.getSubtypeName();
                }
            }
        }
        return typeName;
    }

    /**
     * 返回当前网络别名, 返回 {@link NetworkAlias} 定义的名称：
     * <br>
     * {@code wifi}, {@code 2g}, {@code 3g}, {@code 4g}, {@code null}
     *
     * @param context Context
     * @return 返回当前网络别名
     */
    public static String getCurrentNetworkAlias(Context context) {
        String alias = NetworkAlias.NETWORK_ALIAS_NULL;
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm == null) {
            return alias;
        }

        NetworkInfo mobileInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
        NetworkInfo wifiInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);

        if (null != mobileInfo && mobileInfo.isConnected()) {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            if (tm != null) {
                int netType = tm.getNetworkType();
                switch (netType) {
                    case TelephonyManager.NETWORK_TYPE_GPRS:
                    case TelephonyManager.NETWORK_TYPE_EDGE:
                    case TelephonyManager.NETWORK_TYPE_CDMA:
                    case TelephonyManager.NETWORK_TYPE_1xRTT:
                    case TelephonyManager.NETWORK_TYPE_IDEN:
                        alias = NetworkAlias.NETWORK_ALIAS_2G;
                        break;
                    case TelephonyManager.NETWORK_TYPE_UMTS:
                    case TelephonyManager.NETWORK_TYPE_EVDO_0:
                    case TelephonyManager.NETWORK_TYPE_EVDO_A:
                    case TelephonyManager.NETWORK_TYPE_HSDPA:
                    case TelephonyManager.NETWORK_TYPE_HSUPA:
                    case TelephonyManager.NETWORK_TYPE_HSPA:
                    case TelephonyManager.NETWORK_TYPE_EVDO_B:
                    case TelephonyManager.NETWORK_TYPE_EHRPD:
                    case TelephonyManager.NETWORK_TYPE_HSPAP:
                        alias = NetworkAlias.NETWORK_ALIAS_3G;
                        break;
                    case TelephonyManager.NETWORK_TYPE_LTE:
                        alias = NetworkAlias.NETWORK_ALIAS_4G;
                        break;
                    default:
                        alias = NetworkAlias.NETWORK_ALIAS_NULL;
                        break;
                }
            }
        }
        if (null != wifiInfo && wifiInfo.isConnected()) {
            alias = NetworkAlias.NETWORK_ALIAS_WIFI;
        }
        return alias;
    }

    /**
     * 判断当前活动的网络是否处于移动网络
     * <p/>
     * 另外参考：{@see #isMobileNetwork} , {@see #isWifiNetwork}
     *
     * @param context Context
     * @return 处于移动网络则返回 {@code true}
     * @see {@link #isMobileNetwork(Context)}
     */
    public static boolean isActiveNetworkMobile(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm != null) {
            NetworkInfo ni = cm.getActiveNetworkInfo();
            if (ni != null && isNetworkTypeMobile(ni.getType())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断当前活动的网络是否处于WIFI网络
     * <p/>
     * 另外参考：{@see #isMobileNetwork} , {@see #isWifiNetwork}
     *
     * @param context Context
     * @return 处于WIFI网络则返回 {@code true}
     */
    public static boolean isActiveNetworkWifi(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm != null) {
            NetworkInfo ni = cm.getActiveNetworkInfo();
            if (ni != null && isNetworkTypeWifi(ni.getType())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断是否移动网络,(移动网络已连接上和正在连接中均认为是移动网络)
     *
     * @param context Context
     * @return 是移动网络则返回 {@code true}
     */
    public static boolean isMobileNetwork(final Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (null != cm) {
            try {
                NetworkInfo networkInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
                if (null != networkInfo && networkInfo.isConnectedOrConnecting()) {
                    return true;
                }
            } catch (Exception e) {
                //e.printStackTrace();
            }
        }
        return false;
    }

    /**
     * 判断是否WIFI网络,(WIFI网络已连接上和正在连接中均认为是WIFI网络)
     *
     * @param context Context
     * @return 是WIFI网络则返回 {@code true}
     */
    public static boolean isWifiNetwork(final Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (null != cm) {
            try {
                NetworkInfo networkInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
                if (null != networkInfo && networkInfo.isConnectedOrConnecting()) {
                    return true;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    /**
     * 网络类型是否为 MOBILE
     */
    public static boolean isNetworkTypeMobile(int networkType) {
        switch (networkType) {
            case ConnectivityManager.TYPE_MOBILE:
            case ConnectivityManager.TYPE_MOBILE_MMS:
            case ConnectivityManager.TYPE_MOBILE_SUPL:
            case ConnectivityManager.TYPE_MOBILE_DUN:
            case ConnectivityManager.TYPE_MOBILE_HIPRI:
                return true;
            default:
                return false;
        }
    }

    /**
     * 网络类型是否为 WIFI
     */
    public static boolean isNetworkTypeWifi(int networkType) {
        switch (networkType) {
            case ConnectivityManager.TYPE_WIFI:
                return true;
            default:
                return false;
        }
    }

    /**
     * 获取当前的IP地址
     *
     * @param context Context
     * @return IP地址(如 127.0.0.1)
     */
    public static String getLocalIPAddress(Context context) {
        String ipAddress = getWifiIPAddress(context);
        if (!TextUtils.isEmpty(ipAddress)) {
            return ipAddress;
        }
        // NetworkInterface 通过遍历网络接口获取IP地址
        Enumeration<NetworkInterface> interfaces = null;
        try {
            interfaces = NetworkInterface.getNetworkInterfaces();
        } catch (SocketException e) {
            e.printStackTrace();
        }

        if (interfaces != null) {
            while (interfaces.hasMoreElements()) {
                NetworkInterface networkInterface = interfaces.nextElement();
                Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();

                if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                    while (addresses != null && addresses.hasMoreElements()) {
                        InetAddress inetAddress = addresses.nextElement();
                        if (!inetAddress.isLoopbackAddress() && (inetAddress instanceof Inet4Address)) {
                            return inetAddress.getHostAddress();
                        }
                    }
                } else {
                    while (addresses != null && addresses.hasMoreElements()) {
                        InetAddress inetAddress = addresses.nextElement();
                        if (!inetAddress.isLoopbackAddress()) {
                            return inetAddress.getHostAddress();
                        }
                    }
                }
            }
        }
        return "";
    }

    /**
     * 获取WIFI网卡的IP地址
     */
    private static String getWifiIPAddress(Context context) {
        WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        if (wm == null) {
            return "";
        }
        DhcpInfo dhcpInfo = wm.getDhcpInfo();
        if (dhcpInfo != null) {
            int ipAddress = dhcpInfo.ipAddress;
            return Util.formatIPAddress(ipAddress);
        }
        return "";
    }

    /**
     * 网络别名
     */
    public interface NetworkAlias {
        String NETWORK_ALIAS_NULL = "null";
        String NETWORK_ALIAS_WIFI = "wifi";
        String NETWORK_ALIAS_2G = "2g";
        String NETWORK_ALIAS_3G = "3g";
        String NETWORK_ALIAS_4G = "4g";
    }

    public static final class Util {

        public static final String PATTERN_STRING_IPV4 = "^([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$";

        /**
         * 格式化IP地址 (如 127.0.0.1)
         *
         * @param ip IP地址
         * @return IP地址字符串
         */
        public static String formatIPAddress(int ip) {
            return (ip & 0xff) + "." + ((ip >> 8) & 0xff) + "." + ((ip >> 16) & 0xff) + "." + ((ip >> 24) & 0xff);
        }

        /**
         * 将String类型的IP地址转换成int32类型。将192.168.11.101转换为1812703424
         * <p/>
         * 注：int32 高位在前，地位在后
         *
         * @param ipAddress String类型的IP地址，如：192.168.11.101
         * @return int32类型的IP地址，如：1812703424, 如果IPAddress为null或者不合法，则返回0
         */
        public static int ipAddressToIPv4Int(String ipAddress) {
            if (TextUtils.isEmpty(ipAddress)) {
                return 0;
            }
            if (!ipAddress.matches(PATTERN_STRING_IPV4)) {
                // 如果String类型的IP地址格式不合法。
                return 0;
            }
            String[] array = ipAddress.split("\\.");
            int a = Integer.parseInt(array[0]);
            int b = Integer.parseInt(array[1]) << 8;
            int c = Integer.parseInt(array[2]) << 16;
            int d = Integer.parseInt(array[3]) << 24;
            return a | b | c | d;
        }
    }

    /**
     * 网络类型工具
     * @author wangpeng
     */
    public static class NetworkClassUtil {

        private static final int NETWORK_TYPE_UNAVAILABLE = -1;
        // private static final int NETWORK_TYPE_MOBILE = -100;
        private static final int NETWORK_TYPE_WIFI = -101;

        private static final int NETWORK_CLASS_WIFI = -101;
        private static final int NETWORK_CLASS_UNAVAILABLE = -1;
        /** Unknown network class. */
        private static final int NETWORK_CLASS_UNKNOWN = 0;
        /** Class of broadly defined "2G" networks. */
        private static final int NETWORK_CLASS_2_G = 1;
        /** Class of broadly defined "3G" networks. */
        private static final int NETWORK_CLASS_3_G = 2;
        /** Class of broadly defined "4G" networks. */
        private static final int NETWORK_CLASS_4_G = 3;

        // 适配低版本手机
        /** Network type is unknown */
        public static final int NETWORK_TYPE_UNKNOWN = 0;
        /** Current network is GPRS */
        public static final int NETWORK_TYPE_GPRS = 1;
        /** Current network is EDGE */
        public static final int NETWORK_TYPE_EDGE = 2;
        /** Current network is UMTS */
        public static final int NETWORK_TYPE_UMTS = 3;
        /** Current network is CDMA: Either IS95A or IS95B */
        public static final int NETWORK_TYPE_CDMA = 4;
        /** Current network is EVDO revision 0 */
        public static final int NETWORK_TYPE_EVDO_0 = 5;
        /** Current network is EVDO revision A */
        public static final int NETWORK_TYPE_EVDO_A = 6;
        /** Current network is 1xRTT */
        public static final int NETWORK_TYPE_1xRTT = 7;
        /** Current network is HSDPA */
        public static final int NETWORK_TYPE_HSDPA = 8;
        /** Current network is HSUPA */
        public static final int NETWORK_TYPE_HSUPA = 9;
        /** Current network is HSPA */
        public static final int NETWORK_TYPE_HSPA = 10;
        /** Current network is iDen */
        public static final int NETWORK_TYPE_IDEN = 11;
        /** Current network is EVDO revision B */
        public static final int NETWORK_TYPE_EVDO_B = 12;
        /** Current network is LTE */
        public static final int NETWORK_TYPE_LTE = 13;
        /** Current network is eHRPD */
        public static final int NETWORK_TYPE_EHRPD = 14;
        /** Current network is HSPA+ */
        public static final int NETWORK_TYPE_HSPAP = 15;


        /**
         * 获取运营商
         *
         * @return
         */
        public static String getProvider(Context context) {
            String provider = "未知";
            try {
                TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
                String IMSI = telephonyManager.getSubscriberId();

                if (IMSI == null) {
                    if (TelephonyManager.SIM_STATE_READY == telephonyManager
                            .getSimState()) {
                        String operator = telephonyManager.getSimOperator();
                        if (operator != null) {
                            if (operator.equals("46000")
                                    || operator.equals("46002")
                                    || operator.equals("46007")) {
                                provider = "中国移动";
                            } else if (operator.equals("46001")) {
                                provider = "中国联通";
                            } else if (operator.equals("46003")) {
                                provider = "中国电信";
                            }
                        }
                    }
                } else {
                    if (IMSI.startsWith("46000") || IMSI.startsWith("46002")
                            || IMSI.startsWith("46007")) {
                        provider = "中国移动";
                    } else if (IMSI.startsWith("46001")) {
                        provider = "中国联通";
                    } else if (IMSI.startsWith("46003")) {
                        provider = "中国电信";
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return provider;
        }

        /**
         * 获取网络类型
         *
         * @return
         */
        public static String getCurrentNetworkClassType(Context context) {
            int networkClass = getNetworkClass(context);
            String type = "未知";
            switch (networkClass) {
                case NETWORK_CLASS_UNAVAILABLE:
                    type = "无";
                    break;
                case NETWORK_CLASS_WIFI:
                    type = "Wi-Fi";
                    break;
                case NETWORK_CLASS_2_G:
                    type = "2G";
                    break;
                case NETWORK_CLASS_3_G:
                    type = "3G";
                    break;
                case NETWORK_CLASS_4_G:
                    type = "4G";
                    break;
                case NETWORK_CLASS_UNKNOWN:
                    type = "未知";
                    break;
            }
            return type;
        }

        private static int getNetworkClassByType(int networkType) {
            switch (networkType) {
                case NETWORK_TYPE_UNAVAILABLE:
                    return NETWORK_CLASS_UNAVAILABLE;
                case NETWORK_TYPE_WIFI:
                    return NETWORK_CLASS_WIFI;
                case NETWORK_TYPE_GPRS:
                case NETWORK_TYPE_EDGE:
                case NETWORK_TYPE_CDMA:
                case NETWORK_TYPE_1xRTT:
                case NETWORK_TYPE_IDEN:
                    return NETWORK_CLASS_2_G;
                case NETWORK_TYPE_UMTS:
                case NETWORK_TYPE_EVDO_0:
                case NETWORK_TYPE_EVDO_A:
                case NETWORK_TYPE_HSDPA:
                case NETWORK_TYPE_HSUPA:
                case NETWORK_TYPE_HSPA:
                case NETWORK_TYPE_EVDO_B:
                case NETWORK_TYPE_EHRPD:
                case NETWORK_TYPE_HSPAP:
                    return NETWORK_CLASS_3_G;
                case NETWORK_TYPE_LTE:
                    return NETWORK_CLASS_4_G;
                default:
                    return NETWORK_CLASS_UNKNOWN;
            }
        }

        private static int getNetworkClass(Context context) {
            int networkType = NETWORK_TYPE_UNKNOWN;
            try {
                final NetworkInfo network = ((ConnectivityManager) context
                        .getSystemService(Context.CONNECTIVITY_SERVICE))
                        .getActiveNetworkInfo();
                if (network != null && network.isAvailable()
                        && network.isConnected()) {
                    int type = network.getType();
                    if (type == ConnectivityManager.TYPE_WIFI) {
                        networkType = NETWORK_TYPE_WIFI;
                    } else if (type == ConnectivityManager.TYPE_MOBILE) {
                        TelephonyManager telephonyManager = (TelephonyManager)
                                context.getSystemService(
                                        Context.TELEPHONY_SERVICE);
                        networkType = telephonyManager.getNetworkType();
                    }
                } else {
                    networkType = NETWORK_TYPE_UNAVAILABLE;
                }

            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return getNetworkClassByType(networkType);

        }
    }

}
